/****************************************************************************

	COPYRIGHT(C) MAXSI SOFTWARE, JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010

    This file is part of Maxsi Engine.

    Maxsi Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maxsi Engine is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	*/ #include "MaxsiEngineContributors.h" /*

	If you modify this file, please enter your name below and provide contact
	information in MaxsiEngineContributors.h. For more information please see
	MaxsiEngineContributors.h.
	
	Contributors to this file:

	- Jonas 'Sortie' Termansen
	- [your name here]

	MaxsiEngine.dll
	A linkable version of Maxsi Engine

	MaxsiBuffer.h
	A flexible buffer class.

****************************************************************************/

#ifndef MaxsiBuffer_H
#define MaxsiBuffer_H

namespace MaxsiEngine
{
	// Thread may write to the bufffer
	#define	ME_Buffer_Flag_Write		(0x0000001)

	// Thread may read from the buffer
	#define	ME_Buffer_Flag_Read			(0x0000002)	

	// Thread may access the buffer pointer and modify the buffer, the buffer may not change size
	// when this is set.
	#define	ME_Buffer_Flag_Pointer		(0x0000004)	

	// The buffer contains private data and should be reset as soon as possible.
	#define	ME_Buffer_Flag_Secure		(0x0000008)

	// The buffer is being written to async, do not allow writing!	
	#define	ME_Buffer_Flag_InUse		(0x0000010)	

	#define	ME_Buffer_Flag_Default		(0x0000000)
	#define	ME_Buffer_Flag_AllRights	(ME_Buffer_Flag_Write | ME_Buffer_Flag_Read | ME_Buffer_Flag_Pointer)



	CLASSLINK	ME_Buffer
	{
	public:
		ME_Buffer();
		~ME_Buffer();

	//protected:
	public:
		char*					Buffer;
		size_t					BufferSize;
		size_t					BufferUsed;
		size_t					BufferOffset;
		size_t					BufferIdealSize;
#ifdef _DEBUG
		char*					DebugCaller;
		size_t					DebugLine;
#endif
	protected:
		CRITICAL_SECTION		BufferLock;
	public:

		int						GetBufferFlags();

	private:

		int						SetBufferFlags(int NewFlags);
		int						m_BufferFlags;
	
	public:

#ifdef _DEBUG
#define ME_BUFFER_LOCK_PARAMS ME_Buffer_Flag_AllRights, __FUNCTION__, __LINE__
#define ME_BUFFER_LOCK_PARAMSEX , __FUNCTION__, __LINE__
#define ME_BUFFER_LOCK_EX(Parameter) Lock(Parameter ME_BUFFER_LOCK_PARAMSEX)
#else
#define ME_BUFFER_LOCK_PARAMS
#define ME_BUFFER_LOCK_PARAMSEX
#define ME_BUFFER_LOCK_EX(Parameter) Lock(Parameter ME_BUFFER_LOCK_PARAMSEX)
#endif

		int			Lock(int Flags = ME_Buffer_Flag_AllRights
#ifdef _DEBUG
	, char*		Caller = 0
	, size_t	Line = 0
#endif
		);
		int			Unlock();

		int			Write(ME_Buffer* Input, size_t Size);
		int			Write(char* Input, size_t Size);
		int			Read(char* Dest, size_t Size);

		char*		GetBuffer();			// The real buffer
		char*		GetPointer();			// The current position of the next byte in the buffer
		size_t		GetBufferSize();
		size_t		GetBufferUsed();
		size_t		GetBufferAvailable();
		size_t		GetBufferOffset();
		size_t		GetPointerSizeFollowingData();
		int			SetBufferSize(size_t Size, bool Force = false);
		int			SetBufferOffset(size_t Offset);
		int			SetBufferUsed(size_t Used);
		char*		ProgressPointer(char* Position, size_t Size); // Progresses the pointer provided Size bytes and returns the result if the pointer given is points to somewhere inside the real buffer
		int			ProgressBuffer(size_t Size, bool Force = false); // Progresses the buffer Size bytes forward and returns an error if it goes beyond the size of the buffer

		int			Clear(); // Marks all data in the buffer as read and resets the pointer to the first byte in the buffer
		int			MarkDataAsRead(char* Pointer, size_t Size);

		int			SetInUse();
		int			ClearInUse();
		bool		IsInUse();
		int			MayWrite();
		int			MayRead();

		bool		ShouldDoEvenSillierDebugStuff;

	};

	LINK	ME_Buffer*		CreateBuffer(size_t Size, int flags = ME_Buffer_Flag_Default);
	LINK	bool			DeleteBuffer(ME_Buffer* Buffer);
	LINK	size_t			FindStringInBuffer(ME_Buffer* Buffer, char* String2);
	LINK	size_t			FindStringInBufferEx(ME_Buffer* Buffer, char* String2, size_t String2Len);
}

#endif
